#include <jni.h>
#include <android/bitmap.h>
#include <android/log.h>

#ifdef __cplusplus
extern "C" {
#endif
#ifndef INT64_C
#define INT64_C
#define UINT64_C
#endif

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/pixfmt.h>
#include <android/native_window_jni.h>

#include <stdio.h>
#include <wchar.h>
#include <pthread.h>
#include <unistd.h>
#include <mediaplayer.h>
#include <record.h>
#include <decoder.h>

#define  LOG_TAG    "libplasma"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

#define TAG "video"
MediaPlayer* mPlayer = NULL;
Record* recorder = NULL;
Decoder* decoder = NULL;
JNIEXPORT jint JNICALL
Java_com_gdu_video_RealVideo_openStream( JNIEnv* env,jobject thiz, jstring uriPath,jobject object,jint type)
{

	__android_log_print(ANDROID_LOG_ERROR,TAG,"open url");
	if (mPlayer != NULL && mPlayer->isPlaying()) {
		mPlayer->setStop(0);
		if(type == 1)
		{
			mPlayer->setDecodeType(type);
			mPlayer->setRestart();
		}
		return 0;
	}
	if(mPlayer != NULL && mPlayer->isBegin())
	{
		return 0;
	}

	if (uriPath != NULL && env->GetStringLength(uriPath) > 0)
	{

		const char* str= env->GetStringUTFChars(uriPath, 0);
		char* urlAddress = new char[env->GetStringLength(uriPath) + 1];
		memcpy(urlAddress, str, env->GetStringLength(uriPath) + 1);
		__android_log_print(ANDROID_LOG_ERROR,TAG,"open url");
		env->ReleaseStringUTFChars(uriPath, str);

		if (mPlayer == NULL) {
			mPlayer = new MediaPlayer(env);
		} else {
			if (mPlayer->isPlaying()) {
				mPlayer->stop();
			}
		}

		__android_log_print(ANDROID_LOG_ERROR,TAG,"open url 1");
		if (revokeClass == NULL) {
			jclass revoke_cls_local = env->GetObjectClass(object);
			revokeClass = (jclass) env->NewGlobalRef(revoke_cls_local);
			env->DeleteLocalRef(revoke_cls_local);
		}

		revokeInstance = (jobject) env->NewGlobalRef(object);

		mPlayer->setDataSource(urlAddress);
		__android_log_print(ANDROID_LOG_ERROR,TAG,"open url start");
		mPlayer->start(type);
		mPlayer->setStop(0);
		return 1;
	}
	else
	{
		return -2;
	}
}

JNIEXPORT jint JNICALL
Java_com_gdu_video_RealVideo_closeStream( JNIEnv* env,jobject thiz)
{
	if (mPlayer != NULL) {
		mPlayer->setStop(1);
		mPlayer->stop();
		if (revokeInstance != NULL) {
			env->DeleteGlobalRef(revokeInstance);
			revokeInstance=NULL;
		}
		if (revokeClass != NULL) {
			env->DeleteGlobalRef(revokeClass);
			revokeClass=NULL;
		}
		delete mPlayer;
		mPlayer = NULL;
		return 1;
	}

	return 0;
}

JNIEXPORT void JNICALL
Java_com_gdu_video_RealVideo_pause( JNIEnv* env,jobject thiz)
{
	if(mPlayer!=NULL)
	{
		mPlayer->pause();
	}
}

JNIEXPORT void JNICALL
Java_com_gdu_video_RealVideo_resume( JNIEnv* env,jobject thiz)
{
	if(mPlayer!=NULL)
	{
		mPlayer->resume();
	}
}

JNIEXPORT void JNICALL
Java_com_gdu_video_RealVideo_setRestart( JNIEnv* env,jobject thiz)
{
	__android_log_print(ANDROID_LOG_ERROR,TAG,"set restart");
	if(mPlayer!=NULL)
	{
		mPlayer->setRestart();
	}
}

JNIEXPORT void JNICALL
Java_com_gdu_video_RealVideo_startRecord( JNIEnv* env,jobject thiz,jstring uriPath,jint width,jint height,jint fps)
{
	__android_log_print(ANDROID_LOG_ERROR,TAG,"record start");
	if(recorder==NULL)
	{
		__android_log_print(ANDROID_LOG_ERROR,TAG,"record start new record");
		recorder = new Record();
	}

	if(recorder!=NULL)
	{
		__android_log_print(ANDROID_LOG_ERROR,TAG,"record start trigger start");
		const char *fileName = env->GetStringUTFChars(uriPath, 0);
		recorder->start(fileName,width,height,fps);
	}
}

JNIEXPORT void JNICALL
Java_com_gdu_video_RealVideo_record( JNIEnv* env,jobject thiz,jbyteArray rgbArray,jint pts)
{
	__android_log_print(ANDROID_LOG_ERROR,TAG,"record");
	if(recorder==NULL)
	{
		return;
	}
	if(recorder!=NULL)
	{
		jbyte * rgbData = (jbyte*)env->GetByteArrayElements(rgbArray, 0);
		unsigned char* nativeRGB = (unsigned char*)rgbData;
		recorder->record(nativeRGB,pts);
		env->ReleaseByteArrayElements(rgbArray,rgbData,0);
	}
}

JNIEXPORT void JNICALL
Java_com_gdu_video_RealVideo_stopRecord( JNIEnv* env,jobject thiz)
{
	__android_log_print(ANDROID_LOG_ERROR,TAG,"record stop");
	if(recorder==NULL)
	{
		return;
	}
	if(recorder!=NULL)
	{
		recorder->stop();
	}
	delete recorder;
	recorder = NULL;
}

JNIEXPORT jint JNICALL
Java_com_gdu_video_RealVideo_startDecode( JNIEnv* env,jobject thiz)
{

	if (decoder == NULL) {
		decoder = new Decoder(env);
	} else {
		if (decoder->isPlaying()) {
			decoder->stop();
		}
	}
	decoder->start();
	return 1;

}

JNIEXPORT jint JNICALL
Java_com_gdu_video_RealVideo_startDecoderWriter( JNIEnv* env,
		jobject thiz, jstring uriPath,jobject object)
{
	if(decoder==NULL)
	{
		decoder = new Decoder(env);
	}
	if (revokeClass == NULL)
	{
		jclass revoke_cls_local = env->GetObjectClass(object);
		revokeClass = (jclass) env->NewGlobalRef(revoke_cls_local);
		env->DeleteLocalRef(revoke_cls_local);
	}

	if(revokeInstance == NULL)
	{
		revokeInstance = (jobject) env->NewGlobalRef(object);
	}

	if (decoder != NULL) {
		const char *file = env->GetStringUTFChars(uriPath, 0);
		bool result = decoder->StartScope(file);
		env->ReleaseStringUTFChars(uriPath, file);

		if (result) {
			return 1;
		} else {
			return 0;
		}
	}

	return 0;
}

JNIEXPORT jint JNICALL
Java_com_gdu_video_RealVideo_stopDecoderWriter( JNIEnv* env,
		jobject thiz)
{
	if (decoder != NULL) {
		return decoder->EndScope();
	}

	return 0;
}

JNIEXPORT jint JNICALL
Java_com_gdu_video_RealVideo_setUrl( JNIEnv* env,jobject thiz,jstring url1,jstring url2,jstring url3,jstring url4,jstring url5,jstring url6,jint count)
{
	char* urlAddress1;
	char* urlAddress2;
	char* urlAddress3;
	char* urlAddress4;
	char* urlAddress5;
	char* urlAddress6;
	if (url1 != NULL && env->GetStringLength(url1) > 0)
	{
	const char* str= env->GetStringUTFChars(url1, 0);
	urlAddress1 = new char[env->GetStringLength(url1) + 1];
	memcpy(urlAddress1, str, env->GetStringLength(url1) + 1);
	env->ReleaseStringUTFChars(url1, str);
	}

	if (url2 != NULL && env->GetStringLength(url2) > 0)
	{
	const char* str1= env->GetStringUTFChars(url2, 0);
	urlAddress2 = new char[env->GetStringLength(url2) + 1];
	memcpy(urlAddress2, str1, env->GetStringLength(url2) + 1);
	env->ReleaseStringUTFChars(url2, str1);
	}

	if (url3 != NULL && env->GetStringLength(url3) > 0)
	{
	const char* str2= env->GetStringUTFChars(url3, 0);
	urlAddress3 = new char[env->GetStringLength(url3) + 1];
	memcpy(urlAddress3, str2, env->GetStringLength(url3) + 1);
	env->ReleaseStringUTFChars(url3, str2);
	}

	if (url4 != NULL && env->GetStringLength(url4) > 0)
	{
	const char* str3= env->GetStringUTFChars(url4, 0);
	urlAddress4 = new char[env->GetStringLength(url4) + 1];
	memcpy(urlAddress4, str3, env->GetStringLength(url4) + 1);
	env->ReleaseStringUTFChars(url4, str3);
	}

	if (url5 != NULL && env->GetStringLength(url5) > 0)
	{
	const char* str4= env->GetStringUTFChars(url5, 0);
	urlAddress5 = new char[env->GetStringLength(url5) + 1];
	memcpy(urlAddress5, str4, env->GetStringLength(url5) + 1);
	env->ReleaseStringUTFChars(url5, str4);
	}

	if (url6 != NULL && env->GetStringLength(url6) > 0)
	{
	const char* str5= env->GetStringUTFChars(url6, 0);
	urlAddress6 = new char[env->GetStringLength(url6) + 1];
	memcpy(urlAddress6, str5, env->GetStringLength(url6) + 1);
	env->ReleaseStringUTFChars(url6, str5);
	}
	if(decoder==NULL)
	{
		decoder = new Decoder(env);
	}
	decoder->setDataUrl(urlAddress1,urlAddress2,urlAddress3,urlAddress4,urlAddress5,urlAddress6,count);
}

#ifdef __cplusplus
}
#endif
